package com.boe.hbd.server.processor;

import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.boe.hbd.server.cache.ViewCache;
import com.boe.hbd.server.dao.ViewDao;
import com.boe.hbd.server.model.NearViews;
import com.boe.hbd.server.model.View;
import com.boe.hbd.server.util.Distance;

public class ViewProcessor extends BaseProcessor {

	private ViewDao viewDao = ViewDao.getInstance();
	private ViewCache vc = ViewCache.getInstance();
	private static ViewProcessor instance = new ViewProcessor();

	private ViewProcessor() {
	}

	public static ViewProcessor getInstance() {
		return instance;
	}

	public String deal(String[] args, HttpServletRequest req) {
		String method = args[2];
		if (QUERY.equals(method)) {
			View v = processQuery(Integer.valueOf(args[3]));
			return JSON.toJSONString(v);
		}

		if (FIND.equals(method)) {
			View v = processQuery(args[3]);
			return JSON.toJSONString(v);
		}

		if (ADD.equals(method)) {
			return processAdd(args);
		}

		if (NEAR.equals(method)) {
			int[] dist = new int[MAXNEAR];
			View[] view = new View[MAXNEAR];
			processNear(Double.valueOf(args[3]), Double.valueOf(args[4]), dist,
					view);
			NearViews nv = new NearViews();
			nv.setDist(dist);
			nv.setView(view);
			return JSON.toJSONString(nv);
		}
		return null;
	}

	private String processAdd(String[] args) {

		if (vc.get(args[3]) != null)
			return EXISTED;

		View v = new View();
		v.setName(args[3]);
		v.setDis(args[4]);
		v.setUserID(Integer.valueOf(args[5]));
		v.setPicSeq(Integer.valueOf(args[6]));
		v.setLat(Double.valueOf(args[7]));
		v.setLon(Double.valueOf(args[8]));
		viewDao.insertView(v);
		vc.put(v.getName(), v);
		return SUCCESS;
	}

	private View processQuery(int viewID) {
		View v = viewDao.findView(viewID);
		return v;
	}

	private View processQuery(String name) {
		View v = vc.get(name);
		return v;
	}

	/**
	 * 
	 * @param lat
	 * @param lon
	 * @return
	 */
	private void processNear(double lat, double lon, int[] dist, View[] view) {

		int len = 0;
		int index = 0;
		for (Entry<String, View> e : vc.getMap().entrySet()) {
			double distance = Distance.distance(lat, lon,
					e.getValue().getLat(), e.getValue().getLon());
			if (len < MAXNEAR) {
				dist[len] = (int) distance;
				view[len] = e.getValue();

				if (++len == MAXNEAR) {
					for (int i = 1; i < MAXNEAR; i++) {
						if (dist[index] < dist[i]) {
							index = i;
						}
					}
				}
			} else if (distance < dist[index]) {
				dist[index] = (int) distance;
				view[index] = e.getValue();
				index = 0;
				for (int i = 1; i < MAXNEAR; i++) {
					if (dist[index] < dist[i]) {
						index = i;
					}
				}
			}
		}

		for (int i = MAXNEAR - 1; i > 0; i--) {
			boolean finished = true;
			for (int j = 0; j < i; j++) {
				if (dist[j] > dist[j + 1]) {
					int tempd = dist[j];
					dist[j] = dist[j + 1];
					dist[j + 1] = tempd;
					View tempv = view[j];
					view[j] = view[j + 1];
					view[j + 1] = tempv;
					finished = false;
				}
			}
			if (finished) {
				break;
			}
		}
	}
}
